<MudDialog>
    <DialogContent>
        <MudForm @ref="_form" Model=@Product autocomplete="off">
            <MudTextField Label="Name" HelperText="Product name"
                          @bind-Value="Product.Name" For="@(() => Product.Name)" autocomplete="off" />
            <MudTextField Label="Description" HelperText="Product description"
                          @bind-Value="Product.Description" For="@(() => Product.Description)" autocomplete="off" />
            <MudSelect T="ProductCategory" Label="Category" Variant=Variant.Text AnchorOrigin=Origin.BottomCenter>
                @foreach (var category in Enum.GetValues<ProductCategory>())
                {
                    <MudSelectItem T="ProductCategory" Value=@category />
                }
            </MudSelect>
            <MudNumericField @bind-Value=Product.Quantity Label="Quantity" Variant="Variant.Text" />
            <MudNumericField @bind-Value=Product.UnitPrice Label="Unit Price" Variant="Variant.Text" />
        </MudForm>
    </DialogContent>
    <DialogActions>
        <MudButton OnClick=@Bogus Color=Color.Tertiary Variant=Variant.Filled
                   Size=Size.Large Disabled=@_isSaving>Bogus</MudButton>
        <MudButton OnClick=@Close Color=Color.Secondary Variant=Variant.Filled
                   Size=Size.Large Disabled=@_isSaving>Cancel</MudButton>
        <MudButton StartIcon=@Icons.Material.Filled.Save
                   Color=Color.Primary Size=Size.Large Variant=Variant.Filled
                   OnClick=@Save Disabled=@_isSaving>
            @if (_isSaving)
            {
                <MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true" />
                <MudText Class="ms-2">Saving</MudText>
            }
            else
            {
                <MudText>Save</MudText>
            }
        </MudButton>
    </DialogActions>
</MudDialog>

@code {
    bool _isSaving;
    MudForm? _form;

    public ProductDetails Product { get; set; } = new();

    [CascadingParameter] MudDialogInstance MudDialog { get; set; } = null!;

    [Parameter, EditorRequired]
    public EventCallback<ProductDetails> ProductUpdated { get; set; }

    [Inject]
    public IDialogService DialogService { get; set; } = null!;

    public void Open(string title, Func<ProductDetails, Task> onProductUpdated) =>
        DialogService.Show<ManageProductModal>(
            title, new DialogParameters()
            {
                { 
                    nameof(ProductUpdated),
                    new EventCallbackFactory().Create(
                        this, new Func<ProductDetails, Task>(onProductUpdated)) 
                }
            });

    public void Close() => MudDialog?.Cancel();

    private void Bogus()
    {
        Product = Product.GetBogusFaker().Generate();
        StateHasChanged();
    }

    private Task Save()
    {
        if (_form is not null)
        {
            _form.Validate();
            if (_form.IsValid)
            {
                return OnValidSubmitAsync();
            }
        }

        return Task.CompletedTask;
    }

    private async Task OnValidSubmitAsync()
    {
        if (Product is not null && ProductUpdated.HasDelegate)
        {
            try
            {
                _isSaving = true;
                await ProductUpdated.InvokeAsync(Product);
            }
            finally
            {
                _isSaving = false;
                Close();
            }
        }
    }
}
